﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using ProceduralGolf.generation;

namespace ProceduralGolf
{
    class GameManager
    {
        float[] distances;

        Game game;
        HeightmapGenerator heightmapGenerator;
        GolfCourseLayoutGenerator layoutGenerator;

        readonly int terrainSize;

        readonly int courseWidth;
        readonly int courseHeightOffset;
        
        public GameManager(Game game, int holes, float minDistance, float maxDistance)
        {
            this.game = game;
            terrainSize = Configuration.Config.SettingGroups["Terrain"].Settings["Size"].GetValueAsInt();
            courseWidth = Configuration.Config.SettingGroups["Course"].Settings["Width"].GetValueAsInt();
            courseHeightOffset = Configuration.Config.SettingGroups["Course"].Settings["HeightOffset"].GetValueAsInt();

            heightmapGenerator = new HeightmapGenerator(game);
            layoutGenerator = new GolfCourseLayoutGenerator(game);

            distances = new float[holes];
            Random rand = new Random();
            for (int i = 0; i < holes; ++i)
            {
                distances[i] = MathHelper.Lerp(minDistance, maxDistance, (float)rand.NextDouble());
            }
        }

        public GolfCourse GenerateCourse(int i)
        {
            float distance = distances[i-1];
            Vector2 courseSize = new Vector2(courseWidth, distance+2*courseHeightOffset);
            
            float height = Configuration.Config.SettingGroups["Terrain"].Settings["Height"].GetValueAsFloat();
            int octaves = Configuration.Config.SettingGroups["Terrain"].Settings["Octaves"].GetValueAsInt();
            float lacunarity = Configuration.Config.SettingGroups["Terrain"].Settings["Lacunarity"].GetValueAsFloat();
            float gain = Configuration.Config.SettingGroups["Terrain"].Settings["Gain"].GetValueAsFloat();
            float freq = Configuration.Config.SettingGroups["Terrain"].Settings["Frequency"].GetValueAsFloat();
            float amp = Configuration.Config.SettingGroups["Terrain"].Settings["Amplitude"].GetValueAsFloat();
            float scale = Configuration.Config.SettingGroups["Terrain"].Settings["Scale"].GetValueAsFloat();
            
            Heightmap heightmap = heightmapGenerator.generate(terrainSize + 1, terrainSize + 1, height, octaves, lacunarity, gain, freq, amp);
            GolfCourseLayout layout = layoutGenerator.generateLayout(distance, courseSize, new Vector2(terrainSize, terrainSize));
            
            return new GolfCourse(game, heightmap, layout, scale, i);
        }
    }
}
